#include <algorithm>
#include <cstdio>
using namespace std;

const int N = 200010;
int n, m, tot;
int hash[N], root[N];

struct tree {
	int ls, rs, data;
} tree[N * 100];

struct num {
	int val, id;
	friend bool operator<(const num &a, const num &b) {
		return a.val < b.val;
	}
} nums[N];

int build(int l, int r) {
	int p = ++tot;
	if (l == r) {
		return p;
	}
	int mid = (l + r) >> 1;
	tree[p].ls = build(l, mid);
	tree[p].rs = build(mid + 1, r);
	return p;
}

inline int get(int fir, int sec) {
	return tree[sec].data - tree[fir].data;
}

int query(int fir, int sec, int val, int l, int r) {
	if (l == r) {
		return l;
	}
	int mid = (l + r) >> 1;
	if (get(tree[fir].ls, tree[sec].ls) >= val) {
		return query(tree[fir].ls, tree[sec].ls, val, l, mid);
	}
	else {
		return query(tree[fir].rs, tree[sec].rs, val - get(tree[fir].ls, tree[sec].ls), mid + 1, r);
	}
}

int insert(int ori, int l, int r, int val) {
	int p = ++tot;
	tree[p] = tree[ori];
	if (l == r) {
		tree[p].data++;
		return p;
	}
	int mid = (l + r) >> 1;
	if (val <= mid) {
		tree[p].ls = insert(tree[ori].ls, l, mid, val);
	} else {
		tree[p].rs = insert(tree[ori].rs, mid + 1, r, val);
	}
	tree[p].data = tree[tree[p].ls].data + tree[tree[p].rs].data; //push up
	return p;
}

int main() {
	// freopen("testdata.in", "r", stdin);
	// freopen("testdata.out", "w", stdout);
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++i) {
		scanf("%d", &nums[i].val);
		nums[i].id = i;
	}
	sort(nums + 1, nums + n + 1);
	for (int i = 1; i <= n; ++i) {
		hash[nums[i].id] = i;
	}
	root[0] = build(1, n);
	for (int i = 1; i <= n; ++i)
		root[i] = insert(root[i - 1], 1, n, hash[i]);
	int l = 0, r = 0, k = 0;
	while (m--) {
		scanf("%d%d%d", &l, &r, &k);
		printf("%d\n", nums[query(root[l - 1], root[r], k, 1, n)].val);
	}
	// fclose(stdin);
	// fclose(stdout);
	return 0;
}